<template>
  <div class="align-center my-0" :style="cssVars">
    <v-menu
        v-model="show"
        :offset-y="true"
        :bottom="true"
        :close-on-content-click="false"
        max-height="500px"
    >
      <template #activator="{ attrs, on }">
        <v-text-field
            v-model="treeName"
            :label="label"
            :dense="dense"
            :solo="solo"
            :flat="flat"
            :readonly="!hasInputSearch || !items.length"
            :outlined="outlined"
            hide-details="auto"
            v-bind="attrs"
            :rules="rules"
            :disabled="disabled"
            class="input-field"
            :placeholder="disabled ? '' : defaultPlaceholder"
            @click:clear="onClear"
            @blur="blurName"
            v-on="on"
            :clearable="clearable"
        />
      </template>
      <v-card>
        <v-treeview
            v-if="!hasCheckBox"
            :active="value"
            :search="hasInputSearch ? treeName : empty"
            :filter="filter"
            :item-key="treeKey"
            :item-text="treeLabel"
            :item-children="treeChildrenKey"
            selection-type="independent"
            transition
            activatable
            :open-on-click="openOnClick"
            :items="items"
            selected-color="primary"
            @update:active="activeItem"
            :load-children="fetchChildren"
            :open="open"
        ></v-treeview>
        <v-treeview
            v-if="hasCheckBox"
            :value="value"
            :search="hasInputSearch ? treeName : empty"
            :filter="filter"
            :item-key="treeKey"
            :item-text="treeLabel"
            :item-children="treeChildrenKey"
            transition
            :open-on-click="openOnClick"
            :items="items"
            selectable
            selected-color="primary"
            @input="checkItem"
            :load-children="fetchChildren"
            :open="open"
        ></v-treeview>
      </v-card>
    </v-menu>
  </div>
</template>
<script>
export default {
  model: {
    prop: 'value',
    event: 'change',
  },
  props: {
    rules: { type: Array, default: () => [] },
    items: { type: Array, default: () => [] },
    value: { type: [Array, null], default: () => [] },
    label: { type: String, default: '' },
    treeLabel: { type: String, default: 'name' }, // 树形显示名称
    treeKey: { type: String, default: 'id' }, // 树形唯一ID
    treeChildrenKey: { type: String, default: 'children' }, // 树形子集Key
    placeholder: { type: String, default: '' },
    labelWidth: { type: String, default: '100px' },
    inputWidth: { type: String, default: '200px' },
    disabled: { type: Boolean, default: false },
    readonly: { type: Boolean, default: false },
    openOnClick: { type: Boolean, default: false }, // 点选父级展开子项，父级不选
    hasCheckBox: { type: Boolean, default: false }, // 是否多选框
    hasInputSearch: { type: Boolean, default: true }, // 是否模糊搜索
    clearable: { type: Boolean, default: false },
    outlined: { type: Boolean, default: false },
    solo: { type: Boolean, default: false },
    dense: { type: Boolean, default: false },
    flat: { type: Boolean, default: false },
    fetchChildren: { type: Function, default: null },
  },
  data: () => ({
    empty: '',
    activeVal: [],
    show: false,
    selection: [],
    checkName: [],
    checkId: [],
    tree: [],
    treeName: null,
    treeData: [],
    open: [],
  }),
  computed: {
    filter() {
      return (item, search, textKey) => item[textKey].indexOf(search) > -1;
    },
    defaultPlaceholder() {
      return this.placeholder === '' ? '' : this.placeholder;
    },
    cssVars() {
      return {
        '--labelWidth': this.labelWidth,
        '--inputWidth': this.inputWidth,
      };
    },
  },
  watch: {
    value: {
      immediate: true,
      handler(v) {
        if (v) {
          this.selection = v;
          this.checkName = [];
          this.checkId = [];
          this.showName(this.items);
        }
      },
    },
  },
  mounted() {
    if (this.value) this.$emit('change', this.value);
    // this.selection = this.value;
    // this.checkName = [];
    // this.showName(this.items);
  },
  methods: {
    blurName() {
      // if (!this.selection.length) {
      //   this.treeName = null;
      // }
    },
    resetOpen() {
      this.open = [];
    },
    showName(data, parentName, parentId = []) {
      const treeData = this.selection || [];
      const label = this.treeLabel;
      const value = this.treeKey;
      const children = this.treeChildrenKey;
      // eslint-disable-next-line array-callback-return
      data.map((item) => {
        if (treeData.includes(item[value])) {
          if (!this.checkName.includes(item[label])) {
            this.checkName.push(parentName ? `${parentName}/${item[label]}` : `${item[label]}`);
            this.checkId = parentId.length ? parentId.concat(item[value]) : [].concat(item[value]);
          }
        } else if (item[children]?.length) {
          this.showName(
              item[children],
              parentName ? `${parentName}/${item[label]}` : `${item[label]}`,
              parentId.length ? parentId.concat(item[value]) : [].concat(item[value]),
          );
        }
      });
      this.treeName = this.checkName.toString();
    },
    activeItem(val) {
      this.treeName = null;
      this.checkName = [];
      this.checkId = [];
      this.selection = val;
      this.showName(this.items);
      if (val.length > 0) {
        setTimeout(() => {
          this.show = false;
        }, 500);
      }
      this.$emit('change', val);
    },
    checkItem(val) {
      this.treeName = null;
      this.checkName = [];
      this.checkId = [];
      this.selection = val;
      this.showName(this.items);
      // if (val.length > 0) {
      //   setTimeout(() => {
      //     this.show = false;
      //   }, 500);
      // }
      this.$emit('change', val);
    },
    onClear() {
      this.treeName = null;
      this.checkName = [];
      this.checkId = [];
      this.selection = [];
      this.$emit('change', []);
    },
  },
};
</script>
<style lang="scss" scoped>
.input-field {
  width: var(--inputWidth);
}
.input-label {
  width: var(--labelWidth);
}
//让错误浮动的显示在入力框下面，并不占用页面空间。
//::v-deep .v-text-field__details {
//  position: absolute;
//  top: 3em;
//}

::v-deep .v-treeview-node__label {
  font-size: 14px;
}
</style>